package com.empire.module.member.service.location;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.empire.module.member.controller.admin.location.dto.FrequentLocationDTO;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import com.empire.module.member.controller.admin.location.vo.*;
import com.empire.module.member.dal.dataobject.location.LocationDO;
import com.empire.framework.common.pojo.PageResult;
import com.empire.framework.common.util.object.BeanUtils;

import com.empire.module.member.dal.mysql.location.LocationMapper;

import javax.annotation.Resource;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.empire.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.empire.module.member.enums.ErrorCodeConstants.*;

/**
 * 定位信息 Service 实现类
 *
 * @author 主席大人
 */
@Service
@Validated
public class LocationServiceImpl implements LocationService {

    @Resource
    private LocationMapper locationMapper;

    private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    @Override
    public Long createLocation(LocationSaveReqVO createReqVO) {
        // 先查询
        LambdaUpdateWrapper<LocationDO> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(LocationDO::getPersonId, createReqVO.getPersonId());
        wrapper.eq(LocationDO::getLocationTime, createReqVO.getLocationTime());
        List<LocationDO> locationList = locationMapper.selectList(wrapper);
        if (locationList.isEmpty()) {
            // 插入
            LocationDO location = BeanUtils.toBean(createReqVO, LocationDO.class);
            location.setCreateTime(LocalDateTime.now());
            locationMapper.insert(location);
            // 返回
            return location.getId();
        }
        return locationList.getFirst().getId();
    }

    @Override
    public void updateLocation(LocationSaveReqVO updateReqVO) {
        // 校验存在
        validateLocationExists(updateReqVO.getId());
        // 更新
        LocationDO updateObj = BeanUtils.toBean(updateReqVO, LocationDO.class);
        locationMapper.updateById(updateObj);
    }

    @Override
    public void deleteLocation(Long id) {
        // 校验存在
        validateLocationExists(id);
        // 删除
        locationMapper.deleteById(id);
    }

    private void validateLocationExists(Long id) {
        if (locationMapper.selectById(id) == null) {
            throw exception(LOCATION_NOT_EXISTS);
        }
    }

    @Override
    public LocationDO getLocation(Long id) {
        return locationMapper.selectById(id);
    }

    @Override
    public PageResult<LocationDO> getLocationPage(LocationPageReqVO pageReqVO) {
        return locationMapper.selectPage(pageReqVO);
    }

    @Override
    public List<FrequentLocationDTO> getFrequentLocations(Long personId) {
        return getFrequentLocations(personId, 10); // 默认返回10条
    }

    /**
     * 查询指定人员的常去地统计（支持自定义返回条数）
     */
    @Override
    public List<FrequentLocationDTO> getFrequentLocations(Long personId, Integer limit) {
        // 1. 调用Mapper查询统计数据
        List<Map<String, Object>> dbResults = locationMapper.selectMaps(new QueryWrapper<LocationDO>()
                .eq("person_id", personId) // 筛选指定人员
                .isNotNull("address") // 排除空地址
                .groupBy("address") // 按地址分组
                .select(
                        "address",
                        "COUNT(*) AS count", // 出现次数（对应前端count）
                        "MIN(location_time) AS firstTime", // 首次出现时间
                        "MAX(location_time) AS lastTime", // 末次出现时间
                        "AVG(lng) AS lng", // 平均经度（可选）
                        "AVG(lat) AS lat"  // 平均纬度（可选）
                )
                .orderByDesc("count") // 按出现次数降序
                .last("LIMIT " + limit) // 限制返回条数
        );

        // 2. 转换为前端需要的FrequentLocationDTO
        return dbResults.stream().map(dbResult -> {
            FrequentLocationDTO dto = new FrequentLocationDTO();
            dto.setAddress((String) dbResult.get("address"));
            dto.setCount(((Number) dbResult.get("count")).intValue()); // 转换为int

            // 时间格式转换（LocalDateTime -> String，确保前端可直接使用）
            LocalDateTime firstTime = (LocalDateTime) dbResult.get("firstTime");
            dto.setFirstTime(firstTime != null ? firstTime.format(DATE_TIME_FORMATTER) : null);

            LocalDateTime lastTime = (LocalDateTime) dbResult.get("lastTime");
            dto.setLastTime(lastTime != null ? lastTime.format(DATE_TIME_FORMATTER) : null);

            // 经纬度（可选字段，可能为null）
            dto.setLng(dbResult.get("lng") != null ? ((Number) dbResult.get("lng")).doubleValue() : null);
            dto.setLat(dbResult.get("lat") != null ? ((Number) dbResult.get("lat")).doubleValue() : null);

            return dto;
        }).collect(Collectors.toList());
    }

}